package restfuljobs

import org.springframework.dao.DataIntegrityViolationException
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import groovyx.net.http.Method
import groovy.util.slurpersupport.NodeChild
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class JobApplicationController extends AbstractRestController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
	
	JobApplicationController() {
		path = 'jobApplication'
	}
	
    def index() {
        redirect(action: "list", params: params)
    }

    def list() {
		def jobApplicationInstanceList = []
		
		if(!session.user) {
			redirect(uri: '/')
			return
		}
			
		httpBuilder.get( path: path, query: [userId: session.user.id],
			headers : [Accept : 'application/xml']) { resp, xml ->						

			xml.jobApplication.each {
				def jobApplication = new JobApplicationWrapper()
				jobApplication.id = it.attributes()['id'].toLong()				
				jobApplication.setFromXML(it)
				jobApplicationInstanceList.add(jobApplication)
			}
			
		}
			
       // params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [jobApplicationInstanceList: jobApplicationInstanceList, jobApplicationInstanceTotal: jobApplicationInstanceList.size()]
    }

    def create() {
		
		if (!params.id) {
			redirect(controller: 'jobListing')
			return
		}
		
        def jobApplicationInstance = new JobApplication(params)		
		jobApplicationInstance.jobListing = JobListing.get(params.id)
		
		[jobApplicationInstance: jobApplicationInstance]
    }

	def save() {		
		def jobApplicationInstance = new JobApplication(params)
		
		if (!params.applicantId) {
			if (!params.firstName || !params.lastName) {				
				flash.message = "Please specify your First and Last name."
				render(view: "create", model: [jobApplicationInstance: jobApplicationInstance])
				return
			}
			
			def userXML = "<user><firstName>" + params.firstName + "</firstName>"
			userXML += "<lastName>" + params.lastName + "</lastName>"
			userXML += "<type>APPLICANT</type></user>"
			
			println userXML
			//create User
			httpBuilder.request(Method.POST, "application/xml"){ req ->
				headers.accept = "application/xml"
				uri.path = "user"
				body = userXML
			
				response.success = {resp, xml ->
				   def userId = xml.attributes()['id']
				   println "New User Created $userId"
				   params['applicant.id'] = userId
				}
				
				response.failure = { resp ->
				   flash.message = "Error creating User"
				   render(view: "create", model: [jobApplicationInstance: jobApplicationInstance])
				   return
				}
			}
			
		} else {
		    params['applicant.id'] = params.applicantId			
		}
		
		super.save()
	}
    def show() {
        def jobApplicationInstance
		
		def userId = 0
		
		if (session.user) {
			userId = session.user.id
		}
		
        httpBuilder.request(rootPath, Method.GET, XML ) {
			uri.path = path + "/$params.id"			
			uri.query = [userId: userId]
			
			response.success = { resp, xml ->			  
			  xml.each {												
				jobApplicationInstance = new JobApplicationWrapper()				
				jobApplicationInstance.id = xml.attributes()['id']?.toLong()
				jobApplicationInstance.setFromXML(it)
			  }
			  return [jobApplicationInstance: jobApplicationInstance]
			}
			
			response.failure = { resp ->
				flash.message = message(code: 'default.not.found.message', args: [message(code: path+".label", default: path.capitalize()), params.id])
				redirect(action: "list")
				return
			}
		}		
    }
	
	def accept() {
		changeStatus()
	}

	def reject() {
		changeStatus()
	}
	
	def withdraw() {
		changeStatus()
	}
	
	private void changeStatus() {
		def xmlBuilder = paramsToXML(params)
		
		def userId = 0
		
		if (session.user) {
			userId = session.user.id
		}
		
		println xmlBuilder
		
		httpBuilder.request(Method.PUT, "application/xml"){ req ->
			headers.accept = "application/xml"
			uri.path = path + "/$params.id"
			uri.query = [userId: userId]
			body = xmlBuilder.toString()
		
			response.success = {resp, xml ->
			   redirect(action: "show", id: xml.attributes()['id'])
			}
			
			response.failure = { resp ->
				flash.message = message(code: 'default.not.found.message', args: [message(code: path+".label", default: path.capitalize()), params.id])
				redirect(action: "list")
				return
			}
		}
	}
	
    def edit() {
        def jobApplicationInstance
		
		def userId = 0
		
		if (session.user) {
			userId = session.user.id
		}
		
        httpBuilder.request(rootPath, Method.GET, XML ) {
			uri.path = path + "/$params.id"			
			uri.query = [userId: userId]
			response.success = { resp, xml ->			  
			  xml.each {												
				jobApplicationInstance = new JobApplicationWrapper()				
				jobApplicationInstance.id = xml.attributes()['id']?.toLong()
				jobApplicationInstance.setFromXML(it)
			  }
			  return [jobApplicationInstance: jobApplicationInstance]
			}
			
			response.failure = { resp ->
				flash.message = message(code: 'default.not.found.message', args: [message(code: path+".label", default: path.capitalize()), params.id])
				redirect(action: "list")
				return
			}
		}
    }
}

public class JobApplicationWrapper extends JobApplication {
	private Long id
	
	public Long getId() {
		return id
	}
	
	public void setId(Long id) {
		this.id = id
	}
	
	public void setFromXML(def node) {
		
		node.childNodes().each {
			
			if (it.name == "applicant") {
				this.applicant = new UserWrapper()
				this.applicant.id = it.attributes()['id'].toLong()
				it.each {				
					this.applicant.setFromXML(it)
				}	
			} else if (it.name == "jobListing") {
				this.jobListing = new JobListingWrapper()
				this.jobListing.id = it.attributes()['id'].toLong()	
				it.each {				
					this.jobListing.setFromXML(it)
				}
			} else if (it.name == "reviews") {
			    if (!this.reviews) {
			    	this.reviews = []
			    }
			    
			    it.childNodes().each {
			        def review = new JobApplicationReviewWrapper()
					if (it.attributes()['id']) {
						review.id = it.attributes()['id'].toLong()
					}
					it.each {				
						review.setFromXML(it)
					}
					review.application = this
					this.reviews.add(review)
			    }					
			} else if (it.text().isDouble()) {
				this."$it.name" = Double.parseDouble(it.text())
			} else if(it.name == "dateCreated" || it.name == "lastUpdated") {
				
			} else {
				this."$it.name" = it.text()
			}
			
		}
	}
}